package org.dromara.business.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.business.entity.StatisticsEntity;
import org.dromara.business.enums.NotificationType;
import org.dromara.business.model.TelegramMessage;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

/**
 * Telegram消息模板服务
 * 负责根据不同类型的消息生成格式化的内容
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TelegramMessageTemplateService {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.######");
    
    /**
     * 构建大额交易提醒消息
     */
    public TelegramMessage buildLargeTransactionMessage(Map<String, Object> transactionData, String chatId) {
        String txHash = (String) transactionData.get("txHash");
        BigDecimal amount = (BigDecimal) transactionData.get("amount");
        String tokenSymbol = (String) transactionData.getOrDefault("tokenSymbol", "ETH");
        String fromAddress = (String) transactionData.get("fromAddress");
        String toAddress = (String) transactionData.get("toAddress");
        String network = (String) transactionData.get("network");
        LocalDateTime timestamp = (LocalDateTime) transactionData.get("timestamp");
        BigDecimal gasFee = (BigDecimal) transactionData.get("gasFee");
        
        String content = String.format(
            "%s *大额交易提醒* %s\n\n" +
            "💰 *转账金额*: `%s %s`\n" +
            "📅 *时间*: `%s`\n" +
            "📤 *发送方*: `%s`\n" +
            "📥 *接收方*: `%s`\n" +
            "🔗 *交易哈希*: `%s`\n" +
            "⛽ *Gas费用*: `%s ETH`\n" +
            "🌐 *网络*: `%s`\n" +
            "🔍 [查看详情](https://etherscan.io/tx/%s)",
            NotificationType.LARGE_TRANSACTION.getEmoji(),
            NotificationType.LARGE_TRANSACTION.getEmoji(),
            formatAmount(amount),
            tokenSymbol,
            timestamp.format(DATE_TIME_FORMATTER),
            maskAddress(fromAddress),
            maskAddress(toAddress),
            txHash,
            gasFee != null ? formatAmount(gasFee) : "N/A",
            network,
            txHash
        );
        
        return TelegramMessage.builder()
            .type(NotificationType.LARGE_TRANSACTION)
            .title("大额交易提醒")
            .content(content)
            .chatId(chatId)
            .priority(1) // 最高优先级
            .data(transactionData)
            .build();
    }
    
    /**
     * 构建小时统计报告消息
     */
    public TelegramMessage buildHourlyStatsMessage(StatisticsEntity statisticsEntity, String chatId) {
        StatisticsEntity.Deposit deposit = statisticsEntity.getDeposit();
        StatisticsEntity.Withdrawal withdrawal = statisticsEntity.getWithdrawal();
        
        String content = String.format(
            "%s *小时统计报告* (过去1小时)\n\n" +
            "📈 *入金统计*\n" +
            "┌─ TRON→ZEUS: `%s USDZ` (%d笔)\n" +
            "├─ BSC→ZEUS: `%s USDZ` (%d笔)\n" +
            "└─ POLYGON→ZEUS: `%s USDZ` (%d笔)\n\n" +
            "📉 *出金统计*\n" +
            "┌─ ZEUS→TRON: `%s USDZ` (%d笔)\n" +
            "└─ ZEUS→BSC: `%s USDZ` (%d笔)\n\n" +
            "📊 *总览*\n" +
            "• 总入金: `%s USDZ`\n" +
            "• 总出金: `%s USDZ`\n" +
            "• 净流入: `%s USDZ`\n" +
            "⏰ *统计时间*: `%s`",
            NotificationType.HOURLY_STATISTICS.getEmoji(),
            formatAmount(deposit.getTronToZeusTotalAmount()),
            deposit.getTronToZeusTotal(),
            formatAmount(deposit.getBscToZeusTotalAmount()),
            deposit.getBscToZeusTotal(),
            formatAmount(deposit.getPolygonToZeusTotalAmount()),
            deposit.getPolygonToZeusTotal(),
            formatAmount(withdrawal.getZeusToTronTotalAmount()),
            withdrawal.getZeusToTronTotal(),
            formatAmount(withdrawal.getZeusToBscTotalAmount()),
            withdrawal.getZeusToBscTotal(),
            formatTotalInflow(deposit),
            formatTotalOutflow(withdrawal),
            formatNetFlow(deposit, withdrawal),
            LocalDateTime.now().format(DATE_TIME_FORMATTER)
        );
        
        return TelegramMessage.builder()
            .type(NotificationType.HOURLY_STATISTICS)
            .title("小时统计报告")
            .content(content)
            .chatId(chatId)
            .priority(2)
            .build();
    }
    
    /**
     * 构建日统计报告消息
     */
    public TelegramMessage buildDailyStatsMessage(StatisticsEntity statisticsEntity, String chatId) {
        StatisticsEntity.Deposit deposit = statisticsEntity.getDeposit();
        StatisticsEntity.Withdrawal withdrawal = statisticsEntity.getWithdrawal();
        
        String content = String.format(
            "%s *日统计报告* (%s)\n\n" +
            "📈 *入金统计*\n" +
            "┌─ TRON→ZEUS: `%s USDZ` (%d笔)\n" +
            "├─ BSC→ZEUS: `%s USDZ` (%d笔)\n" +
            "└─ POLYGON→ZEUS: `%s USDZ` (%d笔)\n\n" +
            "📉 *出金统计*\n" +
            "┌─ ZEUS→TRON: `%s USDZ` (%d笔)\n" +
            "└─ ZEUS→BSC: `%s USDZ` (%d笔)\n\n" +
            "📊 *总览*\n" +
            "• 总入金: `%s USDZ` (%d笔)\n" +
            "• 总出金: `%s USDZ` (%d笔)\n" +
            "• 净流入: `%s USDZ`\n" +
            "• 总交易量: `%s USDZ`\n" +
            "📅 *统计日期*: `%s`",
            NotificationType.DAILY_STATISTICS.getEmoji(),
            LocalDate.now().minusDays(1).format(DATE_FORMATTER),
            formatAmount(deposit.getTronToZeusTotalAmount()),
            deposit.getTronToZeusTotal(),
            formatAmount(deposit.getBscToZeusTotalAmount()),
            deposit.getBscToZeusTotal(),
            formatAmount(deposit.getPolygonToZeusTotalAmount()),
            deposit.getPolygonToZeusTotal(),
            formatAmount(withdrawal.getZeusToTronTotalAmount()),
            withdrawal.getZeusToTronTotal(),
            formatAmount(withdrawal.getZeusToBscTotalAmount()),
            withdrawal.getZeusToBscTotal(),
            formatTotalInflow(deposit),
            getTotalDepositCount(deposit),
            formatTotalOutflow(withdrawal),
            getTotalWithdrawalCount(withdrawal),
            formatNetFlow(deposit, withdrawal),
            formatTotalVolume(deposit, withdrawal),
            LocalDate.now().minusDays(1).format(DATE_FORMATTER)
        );
        
        return TelegramMessage.builder()
            .type(NotificationType.DAILY_STATISTICS)
            .title("日统计报告")
            .content(content)
            .chatId(chatId)
            .priority(2)
            .build();
    }
    
    /**
     * 构建系统告警消息
     */
    public TelegramMessage buildSystemAlertMessage(String alertType, String message, String details, String chatId) {
        String content = String.format(
            "%s *系统异常告警* %s\n\n" +
            "🔴 *告警类型*: `%s`\n" +
            "📝 *错误信息*: `%s`\n" +
            "🔍 *详细信息*: \n```\n%s\n```\n" +
            "⏰ *告警时间*: `%s`\n\n" +
            "⚡ 请及时处理此问题！",
            NotificationType.SYSTEM_ALERT.getEmoji(),
            NotificationType.SYSTEM_ALERT.getEmoji(),
            alertType,
            message,
            details,
            LocalDateTime.now().format(DATE_TIME_FORMATTER)
        );
        
        return TelegramMessage.builder()
            .type(NotificationType.SYSTEM_ALERT)
            .title("系统异常告警")
            .content(content)
            .chatId(chatId)
            .priority(1) // 最高优先级
            .build();
    }
    
    /**
     * 构建网络连接异常消息
     */
    public TelegramMessage buildNetworkErrorMessage(String network, String endpoint, String error, String chatId) {
        String content = String.format(
            "%s *网络连接异常* %s\n\n" +
            "🌐 *网络*: `%s`\n" +
            "🔗 *节点*: `%s`\n" +
            "❌ *错误*: `%s`\n" +
            "⏰ *时间*: `%s`\n\n" +
            "🔄 系统将自动尝试重连...",
            NotificationType.NETWORK_ERROR.getEmoji(),
            NotificationType.NETWORK_ERROR.getEmoji(),
            network,
            maskUrl(endpoint),
            error,
            LocalDateTime.now().format(DATE_TIME_FORMATTER)
        );
        
        return TelegramMessage.builder()
            .type(NotificationType.NETWORK_ERROR)
            .title("网络连接异常")
            .content(content)
            .chatId(chatId)
            .priority(1)
            .build();
    }
    
    /**
     * 构建交易失败提醒消息
     */
    public TelegramMessage buildTransactionFailedMessage(String txHash, String reason, String network, String chatId) {
        String content = String.format(
            "%s *交易失败提醒* %s\n\n" +
            "🔗 *交易哈希*: `%s`\n" +
            "❌ *失败原因*: `%s`\n" +
            "🌐 *网络*: `%s`\n" +
            "⏰ *时间*: `%s`\n\n" +
            "🔍 [查看详情](https://etherscan.io/tx/%s)",
            NotificationType.TRANSACTION_FAILED.getEmoji(),
            NotificationType.TRANSACTION_FAILED.getEmoji(),
            txHash,
            reason,
            network,
            LocalDateTime.now().format(DATE_TIME_FORMATTER),
            txHash
        );
        
        return TelegramMessage.builder()
            .type(NotificationType.TRANSACTION_FAILED)
            .title("交易失败提醒")
            .content(content)
            .chatId(chatId)
            .priority(2)
            .build();
    }
    
    // 工具方法
    
    private String formatAmount(BigDecimal amount) {
        if (amount == null) return "0";
        return DECIMAL_FORMAT.format(amount.setScale(6, RoundingMode.DOWN));
    }
    
    private String formatTotalInflow(StatisticsEntity.Deposit deposit) {
        BigDecimal total = deposit.getTronToZeusTotalAmount()
            .add(deposit.getBscToZeusTotalAmount())
            .add(deposit.getPolygonToZeusTotalAmount());
        return formatAmount(total);
    }
    
    private String formatTotalOutflow(StatisticsEntity.Withdrawal withdrawal) {
        BigDecimal total = withdrawal.getZeusToTronTotalAmount()
            .add(withdrawal.getZeusToBscTotalAmount());
        return formatAmount(total);
    }
    
    private String formatNetFlow(StatisticsEntity.Deposit deposit, StatisticsEntity.Withdrawal withdrawal) {
        BigDecimal inflow = deposit.getTronToZeusTotalAmount()
            .add(deposit.getBscToZeusTotalAmount())
            .add(deposit.getPolygonToZeusTotalAmount());
        BigDecimal outflow = withdrawal.getZeusToTronTotalAmount()
            .add(withdrawal.getZeusToBscTotalAmount());
        BigDecimal netFlow = inflow.subtract(outflow);
        String sign = netFlow.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "";
        return sign + formatAmount(netFlow);
    }
    
    private String formatTotalVolume(StatisticsEntity.Deposit deposit, StatisticsEntity.Withdrawal withdrawal) {
        BigDecimal inflow = deposit.getTronToZeusTotalAmount()
            .add(deposit.getBscToZeusTotalAmount())
            .add(deposit.getPolygonToZeusTotalAmount());
        BigDecimal outflow = withdrawal.getZeusToTronTotalAmount()
            .add(withdrawal.getZeusToBscTotalAmount());
        return formatAmount(inflow.add(outflow));
    }
    
    private int getTotalDepositCount(StatisticsEntity.Deposit deposit) {
        return deposit.getTronToZeusTotal() + deposit.getBscToZeusTotal() + deposit.getPolygonToZeusTotal();
    }
    
    private int getTotalWithdrawalCount(StatisticsEntity.Withdrawal withdrawal) {
        return withdrawal.getZeusToTronTotal() + withdrawal.getZeusToBscTotal();
    }
    
    private String maskAddress(String address) {
        if (address == null || address.length() < 10) {
            return address;
        }
        return address.substring(0, 6) + "..." + address.substring(address.length() - 4);
    }
    
    private String maskUrl(String url) {
        if (url == null || url.length() < 20) {
            return url;
        }
        if (url.startsWith("https://")) {
            String domain = url.substring(8).split("/")[0];
            return "https://" + domain + "/...";
        }
        return url.length() > 30 ? url.substring(0, 30) + "..." : url;
    }
}